
Étant passionné d'aviation, je m'efforce toujours d'identifier les avions que j'aperçois. Certains sont relativement faciles à reconnaître grâce à leurs formes originales et spécifiques. Par exemple, les ailes de l'Airbus A380, avec leur forme ovale et leur taille imposante, sont uniques à cet appareil. Pour anecdote, les ailes de l'A380 s'inspirent de celles des rapaces, comme le faucon, l'animal aérien le plus rapide au monde et l'un des plus imposants. Malgré sa taille, il parvient à se stabiliser parfaitement en ajustant l'orientation des plumes situées à l'extrémité de ses ailes. Les concepteurs de l'A380 se sont inspirés de ce mécanisme, ce qui explique pourquoi l'extrémité des ailes de l'A380 ressemble à un petit triangle.
Cependant, pour la majorité des avions, les différences se situent dans de petits détails de la structure de l'appareil. Par exemple, comment distinguer un Airbus A320 d'un Boeing 737? En observant attentivement le nez de l'appareil, on remarque que celui du 737 est légèrement plus géométrique. S'appuyer sur la forme des ailes serait complexe, car les deux modèles possèdent des ailes plates.
Les différences peuvent également résider dans des points plus subtils, comme la taille des réacteurs, ce qui est plus difficile à distinguer à l'œil nu.
Au-delà de la passion, l'identification précise des avions peut s'avérer cruciale. Imaginez une tour de contrôle perdant le contact avec des avions à proximité, et un avion souhaitant atterrir : comment savoir si l'aéroport peut l'accueillir? Un système de détection d'avions, capable d'identifier le modèle de l'appareil et d'informer le pilote via un panneau électrique de la possibilité d'atterrissage, pourrait également alerter les services de secours pour qu'ils se préparent à une intervention d'urgence en cas de risque d'accident.
Ceci n'est qu'un exemple, mais il illustre bien l'utilité et la praticité d'un tel système.
L'enjeu est donc de savoir comment entraîner une intelligence artificielle à reconnaître toutes les subtilités d'un modèle d'avion, afin de pouvoir identifier avec une certaine certitude de quel modèle il s'agit.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import os
from tensorflow.keras.preprocessing.image import ImageDataGenerator
2024-01-24 15:00:12.552093: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations. To enable the following instructions: AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, BatchNormalization
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.callbacks import EarlyStopping, LearningRateScheduler
import seaborn as sns
from tensorflow.keras.preprocessing import image
from PIL import Image
# Repertoire de base
base_dir = "/Users/aliou/Downloads/huge_projects/aircraft_reco/final_data"
train_dir = base_dir + '/train'
test_dir = base_dir + '/test'
# Repertoires des images d'entrainement et de test
a_320_train_dir = train_dir + '/Airbus_320'
a_320_test_dir = test_dir + '/Airbus_320'
a_340_train_dir = train_dir + '/Airbus_340'
a_340_test_dir = test_dir + '/Airbus_340'
a_380_train_dir = train_dir + '/Airbus_380'
a_380_test_dir = test_dir + '/Airbus_380'
b_737_train_dir = train_dir + '/Boeing_737'
b_737_test_dir = test_dir + '/Boeing_737'
b_747_train_dir = train_dir + '/Boeing_747'
b_747_test_dir = test_dir + '/Boeing_747'
b_767_train_dir = train_dir + '/Boeing_767'
b_767_test_dir = test_dir + '/Boeing_767'
embraer_ejet_train_dir = train_dir + '/Embraer_ejet'
embraer_ejet_test_dir = test_dir + '/Embraer_ejet'
# Nombre total d'images contenu dans chaque repertoire
print('total training A320 images :', len(os.listdir( a_320_train_dir ) ))
print('total training A340 images :', len(os.listdir( a_340_train_dir ) ))
print('total training A380 images :', len(os.listdir( a_380_train_dir ) ))
print('total training B737 images :', len(os.listdir( b_737_train_dir ) ))
print('total training B747 images :', len(os.listdir( b_747_train_dir ) ))
print('total training B767 images :', len(os.listdir( b_767_train_dir ) ))
print('total training EEJET images :', len(os.listdir( embraer_ejet_train_dir ) ))
print()
print('total test A320 images :', len(os.listdir( a_320_test_dir ) ))
print('total test A340 images :', len(os.listdir( a_340_test_dir ) ))
print('total test A380 images :', len(os.listdir( a_380_test_dir ) ))
print('total test B737 images :', len(os.listdir( b_737_test_dir ) ))
print('total test B747 images :', len(os.listdir( b_747_test_dir ) ))
print('total test B767 images :', len(os.listdir( b_767_test_dir ) ))
print('total test EEJET images :', len(os.listdir( embraer_ejet_test_dir ) ))
total training A320 images : 101 total training A340 images : 101 total training A380 images : 101 total training B737 images : 101 total training B747 images : 101 total training B767 images : 101 total training EEJET images : 91 total test A320 images : 11 total test A340 images : 11 total test A380 images : 11 total test B737 images : 11 total test B747 images : 11 total test B767 images : 11 total test EEJET images : 11
# Fonction de visualisation
def plot_samples(dir, sample, n_ligne = 3, n_col = 4):
"""
Cette fonction permet de visualiser un échantillons d'image dans une grille NxM (Par défaut: 3 x 4).
Paramètre:
dir: Repertoire où se situe les images,
sample: Echantillons d'image,
n_ligne: Nombre de lignes,
n_col: Nombre de colonnes
"""
plt.figure(figsize = ((n_ligne * n_col), (max(n_ligne, n_col) * 2) ))
for i, aircraft in enumerate(sample): # Itérer sur l'échantillons donné
if aircraft != '.DS_Store': # Ignorer le fichier caché .DS_Store
# Définir une grille de visualisation
ax = plt.subplot(n_ligne, n_col, i + 1)
# Combiner le nom du fichier actuel avec le repertoire donné et plotter.
img = mpimg.imread(os.path.join(dir, aircraft))
plt.axis("off")
plt.imshow(img)
# Mettre le nom du fichier comme titre
ax.set_title(aircraft)
A 320
# Choisir 12 échantillons au hasard puis faire appel à la fonction de plot
a_320_sample = np.random.choice(os.listdir(a_320_train_dir),size = 12)
plot_samples(a_320_train_dir, a_320_sample)
A 340
a_340_sample = np.random.choice(os.listdir(a_340_train_dir),size = 12)
plot_samples(a_340_train_dir, a_340_sample)
A 380
a_380_sample = np.random.choice(os.listdir(a_380_train_dir),size = 12)
plot_samples(a_380_train_dir, a_380_sample)
B 737
b_737_sample = np.random.choice(os.listdir(b_737_train_dir),size = 12)
plot_samples(b_737_train_dir, b_737_sample)
B 747
b_747_sample = np.random.choice(os.listdir(b_747_train_dir),size = 12)
plot_samples(b_747_train_dir, b_747_sample)
B 767
b_767_sample = np.random.choice(os.listdir(b_767_train_dir),size = 12)
plot_samples(b_767_train_dir, b_767_sample)
Embraer Ejet
e_ejet_sample = np.random.choice(os.listdir(embraer_ejet_train_dir),size = 12)
plot_samples(embraer_ejet_train_dir, e_ejet_sample)
Paramètre de l'objet ImageDataGenerator:
Paramètre des générateur d'image:
target_dim = (500, 500)
# Créer un object de la classe ImageDataGenerator
train_datagen = ImageDataGenerator(
rescale = 1/255.0,
rotation_range = 10,
fill_mode = 'nearest'
)
test_datagen = ImageDataGenerator(rescale = 1/255.0)
# Charger et transformer les images des repertoires d'entrainement
train_generator = train_datagen.flow_from_directory(
train_dir,
target_size = target_dim,
batch_size = 10,
class_mode = 'sparse',
color_mode = 'grayscale'
)
test_generator = test_datagen.flow_from_directory(
test_dir,
target_size = target_dim,
batch_size = 10,
class_mode = 'sparse',
color_mode = 'grayscale'
)
Found 690 images belonging to 7 classes. Found 70 images belonging to 7 classes.
# Comment est-ce que le générateur à ordonné les classes
test_generator.class_indices
{'Airbus_320': 0,
'Airbus_340': 1,
'Airbus_380': 2,
'Boeing_737': 3,
'Boeing_747': 4,
'Boeing_767': 5,
'Embraer_ejet': 6}
input_shape = (500, 500, 1) : J'ai utilisé plusieurs input shape au final 500x500 marche mieux pour l'entrainement, car les images du dataset sont de qualité relativement bonne entre 600x? à du HD. Le paramètre 1, spécifie le nombre de channel qu'attendra le modèle 1: pour des images de gris et 3: pour des rgb.
CNN: J'ai opté pour un cnn car le meilleur choix.
input_shape = (500, 500, 1)
num_classes = 7 # Classes identifier
model = Sequential([
Conv2D(4, (3, 3), input_shape=input_shape, activation='relu'),
MaxPooling2D((2, 2)),
BatchNormalization(),
Conv2D(8, (3, 3), activation='relu'),
MaxPooling2D((2, 2)),
BatchNormalization(),
Conv2D(16, (3, 3), activation='relu'),
MaxPooling2D((2, 2)),
BatchNormalization(),
Flatten(),
Dropout(0.4),
Dense(32, activation='relu'),
BatchNormalization(),
Dense(num_classes, activation='softmax') # Use softmax for multi-class classification
])
model.summary()
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 498, 498, 4) 40
max_pooling2d (MaxPooling2 (None, 249, 249, 4) 0
D)
batch_normalization (Batch (None, 249, 249, 4) 16
Normalization)
conv2d_1 (Conv2D) (None, 247, 247, 8) 296
max_pooling2d_1 (MaxPoolin (None, 123, 123, 8) 0
g2D)
batch_normalization_1 (Bat (None, 123, 123, 8) 32
chNormalization)
conv2d_2 (Conv2D) (None, 121, 121, 16) 1168
max_pooling2d_2 (MaxPoolin (None, 60, 60, 16) 0
g2D)
batch_normalization_2 (Bat (None, 60, 60, 16) 64
chNormalization)
flatten (Flatten) (None, 57600) 0
dropout (Dropout) (None, 57600) 0
dense (Dense) (None, 32) 1843232
batch_normalization_3 (Bat (None, 32) 128
chNormalization)
dense_1 (Dense) (None, 7) 231
=================================================================
Total params: 1845207 (7.04 MB)
Trainable params: 1845087 (7.04 MB)
Non-trainable params: 120 (480.00 Byte)
_________________________________________________________________
# Compile the model
model.compile(optimizer = Adam(),
loss = 'sparse_categorical_crossentropy',
metrics = ['accuracy'])
Créer un objet de la classe EarlyStopping pour surveiller la loss avec un niveau de patience de 5 steps:
early_stopping = EarlyStopping(monitor = 'val_loss', patience = 5, restore_best_weights = True)
Optimiser le taux d'apprentissage au délà de 10 epochs pour améliorer l'apprentissage
def learning_rate_scheduler(epochs):
if epochs < 10:
return 0.001
else:
return 0.001 * tf.math.exp(0.1 * (10 - epochs))
# Créer un objet de la classe 'LearningRateScheduler' et envoyer la fonction de programmation du taux d'entrainement.
learning_rate_schedule = LearningRateScheduler(learning_rate_scheduler)
Entrainement du modèle:
history = model.fit(
train_generator,
steps_per_epoch = len(train_generator),
epochs = 30,
validation_data = test_generator,
validation_steps = len(test_generator),
callbacks = [early_stopping, learning_rate_schedule]
)
Epoch 1/30 69/69 [==============================] - 68s 950ms/step - loss: 2.0779 - accuracy: 0.2188 - val_loss: 2.1155 - val_accuracy: 0.1429 - lr: 0.0010 Epoch 2/30 69/69 [==============================] - 65s 939ms/step - loss: 1.6853 - accuracy: 0.3725 - val_loss: 2.5495 - val_accuracy: 0.1571 - lr: 0.0010 Epoch 3/30 69/69 [==============================] - 65s 941ms/step - loss: 1.4748 - accuracy: 0.4696 - val_loss: 2.5210 - val_accuracy: 0.1714 - lr: 0.0010 Epoch 4/30 69/69 [==============================] - 65s 942ms/step - loss: 1.3542 - accuracy: 0.5116 - val_loss: 2.3159 - val_accuracy: 0.1857 - lr: 0.0010 Epoch 5/30 69/69 [==============================] - 65s 939ms/step - loss: 1.1072 - accuracy: 0.6101 - val_loss: 1.9374 - val_accuracy: 0.2714 - lr: 0.0010 Epoch 6/30 69/69 [==============================] - 67s 974ms/step - loss: 0.9232 - accuracy: 0.7014 - val_loss: 1.9540 - val_accuracy: 0.2714 - lr: 0.0010 Epoch 7/30 69/69 [==============================] - 65s 927ms/step - loss: 0.8174 - accuracy: 0.7609 - val_loss: 1.4949 - val_accuracy: 0.5143 - lr: 0.0010 Epoch 8/30 69/69 [==============================] - 66s 957ms/step - loss: 0.6936 - accuracy: 0.7783 - val_loss: 1.6028 - val_accuracy: 0.4571 - lr: 0.0010 Epoch 9/30 69/69 [==============================] - 67s 965ms/step - loss: 0.6030 - accuracy: 0.8420 - val_loss: 1.6819 - val_accuracy: 0.4714 - lr: 0.0010 Epoch 10/30 69/69 [==============================] - 65s 940ms/step - loss: 0.6431 - accuracy: 0.7884 - val_loss: 1.3184 - val_accuracy: 0.6429 - lr: 0.0010 Epoch 11/30 69/69 [==============================] - 59s 856ms/step - loss: 0.5031 - accuracy: 0.8580 - val_loss: 1.3308 - val_accuracy: 0.6000 - lr: 0.0010 Epoch 12/30 69/69 [==============================] - 59s 842ms/step - loss: 0.4055 - accuracy: 0.8754 - val_loss: 1.7477 - val_accuracy: 0.5143 - lr: 9.0484e-04 Epoch 13/30 69/69 [==============================] - 59s 849ms/step - loss: 0.3841 - accuracy: 0.8870 - val_loss: 1.3965 - val_accuracy: 0.6429 - lr: 8.1873e-04 Epoch 14/30 69/69 [==============================] - 59s 851ms/step - loss: 0.3751 - accuracy: 0.9000 - val_loss: 1.4221 - val_accuracy: 0.6143 - lr: 7.4082e-04 Epoch 15/30 69/69 [==============================] - 60s 852ms/step - loss: 0.3432 - accuracy: 0.9058 - val_loss: 1.2717 - val_accuracy: 0.6571 - lr: 6.7032e-04 Epoch 16/30 69/69 [==============================] - 60s 861ms/step - loss: 0.3333 - accuracy: 0.8971 - val_loss: 1.4467 - val_accuracy: 0.6429 - lr: 6.0653e-04 Epoch 17/30 69/69 [==============================] - 60s 873ms/step - loss: 0.2902 - accuracy: 0.9261 - val_loss: 1.5307 - val_accuracy: 0.6000 - lr: 5.4881e-04 Epoch 18/30 69/69 [==============================] - 62s 877ms/step - loss: 0.2400 - accuracy: 0.9333 - val_loss: 1.3586 - val_accuracy: 0.6429 - lr: 4.9659e-04 Epoch 19/30 69/69 [==============================] - 61s 860ms/step - loss: 0.2231 - accuracy: 0.9478 - val_loss: 1.4792 - val_accuracy: 0.6143 - lr: 4.4933e-04 Epoch 20/30 69/69 [==============================] - 60s 870ms/step - loss: 0.1809 - accuracy: 0.9609 - val_loss: 1.4355 - val_accuracy: 0.6000 - lr: 4.0657e-04
# Les variables de mesure de performances
history.history.keys()
dict_keys(['loss', 'accuracy', 'val_loss', 'val_accuracy', 'lr'])
acc = history.history['accuracy'][-1]
loss = history.history['loss'][-1]
print(f"accuracy: {acc}\nloss: {loss}")
accuracy: 0.960869550704956 loss: 0.18091294169425964
sns.set()
plt.figure(figsize = (12,6))
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'Validation'], loc='upper left')
plt.show()
sns.set()
plt.figure(figsize = (12,6))
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'Validation loss'], loc='upper left')
plt.show()
A partir des courbes de train/validation et loss/validation, on constate un certains écart et une certaine variances entre les courbes, on peut en conclure que l'apprentissage n'est peut être optimiser avec plus de données et une optimisation des hyperparamètres on devrait pour obtenir une meilleur courbe d'apprentissage.
# Créer un dictionnaire des classes pour déterminer la classe prédite de manière dynamique.
classes = {
0 : 'Airbus A 320',
1 : 'Airbus A 340',
2 : 'Airbus A 380',
3 : 'Boeing 737',
4 : 'Boeing 747',
5 : 'Boeing 767',
6 : 'Embraer E jet'
}
def rgb_to_grayscale(path):
"""
Transforme l'image à prédire, pour quelle puisse être accepté par le modèle.
Paramètre:
path: Chemin d'accès de l'image.
"""
rgb_image = Image.open(path) # Ouvrir l'image
grayscale_image = rgb_image.convert('L') # Transformer l'image en gris.
grayscale_image = np.array(grayscale_image) # Convertir l'image en une matrice de numpy
# Rédimentionner à l'(input shape) souhaité
np_image = np.array(Image.fromarray(grayscale_image).resize((500, 500)))
# Normaliser l'image
np_image_nomalized = np_image / 255.0
return np_image_nomalized
def predictions_test_set(path, cl : int):
"""
Cette fonction permet de predir chaque élément contenu dans un repertoire donnée.
Paramètre:
path: Chemin d'accès du repertoire.
cl: Classe des images du repertoire. (Car je l'ai grouper par classe)
"""
files = os.listdir(path) # Obtenir une liste des noms des images du répertoire
n_true = 0 # Variable de comptage des vraies prédictions
for _, filename in enumerate(files):
if filename != '.DS_Store': # Ignorer le fichier caché '.DS_Store'
img = rgb_to_grayscale(path + '/' + filename) # Construire le chémin de l'image et la transformer
preds_probs = model.predict(np.expand_dims(img, axis = 0)) # Obtenir la liste des prédictions
predicted = np.argmax(preds_probs, axis = 1)[0] # Sélectionner le maximum et accéder à l'indice
# Afficher les prédictions en fonction de la véracité de la prédiction
if cl == predicted:
n_true += 1
print(f"True: Image: {filename}, predicted: {classes[predicted]}")
else:
print(f"False: Image: {filename}, predicted: {classes[predicted]}")
print('************')
print(f"True predictions: {n_true} / {len(files) - 1}") # Afficher la rapport des vraies prédictions
predictions_test_set(a_380_test_dir, 2)
1/1 [==============================] - 0s 55ms/step True: Image: a380_9872518.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 49ms/step True: Image: a380_9716284.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 62ms/step True: Image: a380_1979068.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 46ms/step True: Image: a380_9861562.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 54ms/step True: Image: a380_9826128.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 47ms/step True: Image: a380_9817263.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 51ms/step True: Image: a380_9832618.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 46ms/step True: Image: a380_9732825.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 50ms/step True: Image: a380_9871652.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 48ms/step True: Image: a380_9865134.jpg, predicted: Airbus A 380 ************ True predictions: 10 / 10
predictions_test_set(a_320_test_dir, 0)
1/1 [==============================] - 0s 49ms/step True: Image: a320_2194912.jpg, predicted: Airbus A 320 1/1 [==============================] - 0s 53ms/step True: Image: a320_1838645.jpg, predicted: Airbus A 320 1/1 [==============================] - 0s 54ms/step True: Image: a320_1882508.jpg, predicted: Airbus A 320 1/1 [==============================] - 0s 49ms/step False: Image: a320_1921311.jpg, predicted: Embraer E jet 1/1 [==============================] - 0s 53ms/step True: Image: a320_2164953.jpg, predicted: Airbus A 320 1/1 [==============================] - 0s 66ms/step True: Image: a320_1878567.jpg, predicted: Airbus A 320 1/1 [==============================] - 0s 70ms/step False: Image: a320_1876402.jpg, predicted: Boeing 747 1/1 [==============================] - 0s 48ms/step False: Image: a320_1871273.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 51ms/step True: Image: a320_1813838.jpg, predicted: Airbus A 320 1/1 [==============================] - 0s 49ms/step False: Image: a320_2069707.jpg, predicted: Boeing 767 ************ True predictions: 6 / 10
predictions_test_set(a_340_test_dir, 1)
1/1 [==============================] - 0s 51ms/step False: Image: a340_1699455.jpg, predicted: Boeing 747 1/1 [==============================] - 0s 48ms/step False: Image: a340_2130085.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 51ms/step True: Image: a340_2193516.jpg, predicted: Airbus A 340 1/1 [==============================] - 0s 50ms/step False: Image: a340_1794927.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 48ms/step True: Image: a340_2084805.jpg, predicted: Airbus A 340 1/1 [==============================] - 0s 54ms/step False: Image: a340_2215390.jpg, predicted: Boeing 767 1/1 [==============================] - 0s 50ms/step False: Image: a340_2177828.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 50ms/step False: Image: a340_1718898.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 46ms/step True: Image: a340_1634020.jpg, predicted: Airbus A 340 1/1 [==============================] - 0s 49ms/step True: Image: a340_1732551.jpg, predicted: Airbus A 340 ************ True predictions: 4 / 10
predictions_test_set(b_737_test_dir, 3)
1/1 [==============================] - 0s 48ms/step True: Image: b737_1237623.jpg, predicted: Boeing 737 1/1 [==============================] - 0s 46ms/step True: Image: b737_1163792.jpg, predicted: Boeing 737 1/1 [==============================] - 0s 52ms/step True: Image: b737_0851302.jpg, predicted: Boeing 737 1/1 [==============================] - 0s 50ms/step True: Image: b737_0558343.jpg, predicted: Boeing 737 1/1 [==============================] - 0s 51ms/step True: Image: b737_1115400.jpg, predicted: Boeing 737 1/1 [==============================] - 0s 51ms/step True: Image: b737_0237107.jpg, predicted: Boeing 737 1/1 [==============================] - 0s 51ms/step False: Image: b737_0218042.jpg, predicted: Boeing 747 1/1 [==============================] - 0s 52ms/step True: Image: b737_0973082.jpg, predicted: Boeing 737 1/1 [==============================] - 0s 48ms/step False: Image: b737_0482804.jpg, predicted: Embraer E jet 1/1 [==============================] - 0s 50ms/step True: Image: b737_0523207.jpg, predicted: Boeing 737 ************ True predictions: 8 / 10
predictions_test_set(b_747_test_dir, 4)
1/1 [==============================] - 0s 50ms/step False: Image: b747_1836113.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 51ms/step False: Image: b747_2162684.jpg, predicted: Airbus A 320 1/1 [==============================] - 0s 51ms/step True: Image: b747_1896036.jpg, predicted: Boeing 747 1/1 [==============================] - 0s 52ms/step False: Image: b747_1707900.jpg, predicted: Boeing 767 1/1 [==============================] - 0s 52ms/step False: Image: b747_2226313.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 51ms/step False: Image: b747_2167150.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 50ms/step True: Image: b747_1864991.jpg, predicted: Boeing 747 1/1 [==============================] - 0s 50ms/step False: Image: b747_1739526.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 51ms/step True: Image: b747_2217964.jpg, predicted: Boeing 747 1/1 [==============================] - 0s 52ms/step False: Image: b747_1821602.jpg, predicted: Boeing 767 ************ True predictions: 3 / 10
predictions_test_set(b_767_test_dir, 5)
1/1 [==============================] - 0s 49ms/step True: Image: b767_0981955.jpg, predicted: Boeing 767 1/1 [==============================] - 0s 49ms/step True: Image: b767_0905077.jpg, predicted: Boeing 767 1/1 [==============================] - 0s 54ms/step True: Image: b767_0940358.jpg, predicted: Boeing 767 1/1 [==============================] - 0s 58ms/step True: Image: b767_0097107.jpg, predicted: Boeing 767 1/1 [==============================] - 0s 47ms/step True: Image: b767_0087248.jpg, predicted: Boeing 767 1/1 [==============================] - 0s 49ms/step True: Image: b767_2054456.jpg, predicted: Boeing 767 1/1 [==============================] - 0s 51ms/step True: Image: b767_2021838.jpg, predicted: Boeing 767 1/1 [==============================] - 0s 50ms/step True: Image: b767_0867007.jpg, predicted: Boeing 767 1/1 [==============================] - 0s 53ms/step True: Image: b767_2259027.jpg, predicted: Boeing 767 1/1 [==============================] - 0s 47ms/step True: Image: b767_2209439.jpg, predicted: Boeing 767 ************ True predictions: 10 / 10
predictions_test_set(embraer_ejet_test_dir, 6)
1/1 [==============================] - 0s 51ms/step False: Image: ejet_1912564.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 47ms/step False: Image: ejet_2156795.jpg, predicted: Boeing 747 1/1 [==============================] - 0s 51ms/step False: Image: ejet_1917223.jpg, predicted: Airbus A 380 1/1 [==============================] - 0s 58ms/step False: Image: ejet_2259453.jpg, predicted: Boeing 737 1/1 [==============================] - 0s 48ms/step True: Image: ejet_2094472.jpg, predicted: Embraer E jet 1/1 [==============================] - 0s 48ms/step True: Image: ejet_1398982.jpg, predicted: Embraer E jet 1/1 [==============================] - 0s 49ms/step True: Image: ejet_1367016.jpg, predicted: Embraer E jet 1/1 [==============================] - 0s 47ms/step True: Image: ejet_1687909.jpg, predicted: Embraer E jet 1/1 [==============================] - 0s 49ms/step True: Image: ejet_1796759.jpg, predicted: Embraer E jet 1/1 [==============================] - 0s 49ms/step True: Image: ejet_1679201.jpg, predicted: Embraer E jet ************ True predictions: 6 / 10
path = '/Users/aliou/Downloads/huge_projects/aircraft_reco/tests'
def plot_test_set_results(path, n_ligne = 3, n_col = 4):
"""
Cette fonction prends en paramètre un chemin d'accès, le nombre de lignes et de colonnes (par défaut 3,4) pour éffectuer des prédictions
sur toutes les images contenu dans le repertoire, éffectuer les prédictions et afficher en comparant les résultats.
Paramètres:
- path: Chemin où sont contenu les images. (Une boucle créera une la source complète image par image afin de la prédire)
- n_ligne: Nombre de ligne.
- n_col: Nombre de colonnes.
(Les lignes et colonnes finales seront calculées)
"""
plt.figure(figsize = ((n_ligne * n_col), (max(n_ligne, n_col) * 2) ))
files = os.listdir(path)
for i, filename in enumerate(files):
if filename != '.DS_Store':
ax = plt.subplot(n_ligne, n_col, i + 1)
x = rgb_to_grayscale(path + '/' + filename)
preds_probs = model.predict(np.expand_dims(x, axis = 0))
predicted = np.argmax(preds_probs, axis = 1)[0]
img = image.load_img(path + '/' + filename,target_size = target_dim)
plt.axis("off")
plt.imshow(img)
if predicted == 0 :
ax.set_title(f"{filename[0:4]} model says : A 320'")
elif predicted == 1:
ax.set_title(f"{filename[0:4]} model says : A 340")
elif predicted == 2:
ax.set_title(f"{filename[0:4]} model says : A 380")
elif predicted == 3:
ax.set_title(f"{filename[0:4]} model says : B 737")
elif predicted == 4:
ax.set_title(f"{filename[0:4]} model says : B 747")
elif predicted == 5:
ax.set_title(f"{filename[0:4]} model says : B 767")
elif predicted == 6:
ax.set_title(f"{filename[0:4]} model says : E jet")
plot_test_set_results(path)
1/1 [==============================] - 0s 52ms/step 1/1 [==============================] - 0s 61ms/step 1/1 [==============================] - 0s 51ms/step 1/1 [==============================] - 0s 49ms/step 1/1 [==============================] - 0s 47ms/step 1/1 [==============================] - 0s 54ms/step 1/1 [==============================] - 0s 60ms/step 1/1 [==============================] - 0s 76ms/step 1/1 [==============================] - 0s 114ms/step 1/1 [==============================] - 0s 46ms/step 1/1 [==============================] - 0s 48ms/step 1/1 [==============================] - 0s 49ms/step 1/1 [==============================] - 0s 50ms/step 1/1 [==============================] - 0s 48ms/step
Save model
#model.save('aircraft_model_096.keras', overwrite = True)